var DragBoxManager = {};

DragBoxManager.target_class = "dbm_target";
DragBoxManager.box_class = "dbm_box";
DragBoxManager.container_class = "dbm_box";

DragBoxManager._boxes = [];
DragBoxManager._targets = [];
DragBoxManager._target_pos = [];

DragBoxManager.events = {
	"start" : null,			// cback ( obj ) -> T/F. If T the drag will actually start
	"move"	: null,			// cback ( obj, x, y ) -> returns a struct with ( obj, x, y )
	"end"	: null,			// cback ( obj )
	"change" : null			// cback ( obj )
};

DragBoxManager.DragBox = function ( el, target )
{
	this.el = el;
	this.target = target;

	this.get_heigth = function ()
	{
		return this.el.offsetHeight;
	};

	this.get_y_offset = function ()
	{
		return liwe.dom.get_offset_top ( this.el );
	};

	this.get_bottom = function ()
	{
		return this.get_y_offset () + this.el.offsetHeight;
	};

	this.el._instance = this;
}


DragBoxManager.init = function ( lock_x, lock_y )
{
	drag.start_func = DragBoxManager._start_func;
	drag.move_func = DragBoxManager._move_func;
	drag.release_func = DragBoxManager._release_func;

	drag.lock_x = lock_x;
	drag.lock_y = lock_y;

	drag.container_class = DragBoxManager.container_class;
	drag.handle_class = DragBoxManager.box_class;
	//drag.exclude_class = "drag_exclude";

	DragBoxManager._targets = [];
	DragBoxManager._boxes = [];
	DragBoxManager._target_pos = [];

	DragBoxManager._iter_dom ( document.body );
};


DragBoxManager._iter_dom = function ( el )
{
	var i, l = el.childNodes.length;

	//if ( typeof el [ "className" ] != "undefined" && el [ 'className' ] == DragBoxManager.target_class )
	if ( liwe.dom.has_class ( el, DragBoxManager.target_class ) )
	{
		DragBoxManager._targets.push ( el );

		var x = liwe.dom.get_offset_left ( el );
		var w = el.offsetWidth;

		el._dbm_x1 = x;
		el._dbm_x2 = w + x;

		DragBoxManager._target_pos.push ( el._dbm_x1, el._dbm_x2 );

		for ( i = 0; i < l; i ++ )
		{
			var c = el.childNodes [ i ];
			//if ( c [ "className" ] != DragBoxManager.container_class ) continue;
			if ( ! liwe.dom.has_class ( c, DragBoxManager.container_class ) ) continue;
			
			DragBoxManager._boxes.push ( new DragBoxManager.DragBox ( c, el ) );
		}
	} else {
		for ( i = 0; i < l; i ++ )
			arguments.callee ( el.childNodes [ i ] );
	}
};


DragBoxManager._start_func = function ( obj )
{
	if ( DragBoxManager.events [ 'start' ] ) 
		if ( ! DragBoxManager.events [ 'start' ] ( obj ) ) return;

	// DRAG START
	var caret = document.createElement ( "DIV" );
	caret.id = "dbm:caret";
	caret.className = "dbm_caret";
	caret.style.width = obj.clientWidth + "px";
	caret.style.height = obj.clientHeight + "px";

	var parent = obj.parentNode;
	parent.insertBefore ( caret, obj );
};


DragBoxManager._move_func = function ( obj, x, y )
{
	if ( DragBoxManager.events [ 'move' ] ) 
	{
		struct = DragBoxManager.events [ 'move' ] ( obj, x, y );
		x = struct.x;
		y = struct.y;
		obj = struct.obj;
	}

	// DRAG MOVE
	var col = null, x1, x2;
	var i, l = DragBoxManager._target_pos.length;
	for ( i = 0; i < l; i += 2 )
	{
		x1 = DragBoxManager._target_pos [ i ];
		x2 = DragBoxManager._target_pos [ i + 1 ];

		if ( x >= x1 && x <= x2 )
		{
			col = DragBoxManager._targets [ i / 2 ];
			break;
		}
	}

	if ( ! col ) return;

	var elems = col.childNodes;
	var cel = elems.length;
	var t, box = null, b;
	for ( t = 0; t < cel; t ++ )
	{
		b = elems [ t ];

		if ( ! b.className || b.className.indexOf ( DragBoxManager.container_class ) == -1 ) continue;
		var y2 = b._instance.get_bottom ();

		if ( y < y2 )
		{
			box = b;
			break;
		}
	}

	var caret = document.getElementById ( "dbm:caret" );
	caret.parentNode.removeChild ( caret );

	if ( box )
		box.parentNode.insertBefore ( caret, box );
	else
		col.appendChild ( caret );
};


DragBoxManager._release_func = function ( obj )
{
	// DRAG END
	obj.style.position = "static";

	obj.parentNode.removeChild ( obj );

	var caret = document.getElementById ( "dbm:caret" );
	caret.parentNode.insertBefore ( obj, caret );
	caret.parentNode.removeChild ( caret );

	if ( DragBoxManager.events [ 'end' ] ) DragBoxManager.events [ 'end' ] ( obj );
	if ( DragBoxManager.events [ 'change' ] ) DragBoxManager.events [ 'change' ] ( obj );
};

